#pragma once
#include <Arbitrator.h>
#include <InformationManager.h>
#include <BWAPI.h>
#include "../BasicAIModule/Source/PheramoneTrail.h"

class ScoutManager : public Arbitrator::Controller<BWAPI::Unit*,double>
{
  public:
    class ScoutData
    {
      public:
        enum ScoutMode
        {
          Idle,
          Searching,
          Roaming,
          Harassing,
          Fleeing,
		      Spying, // TONG: hang around until a threat appears --> Fleeing
        };
        ScoutData(){ mode = Idle; }
        BWTA::BaseLocation* target;
        BWTA::BaseLocation* lastTarget;
        ScoutMode mode;
    };
    class ScoutPriority
    {
      public:
        enum JobStatus {
          Dormant,      // foodCount threshold has not been reached
          Triggered,    // theshold met and bidding on units
          Assigned,     // unit acquired and assigned
          Retired,      // unit scout completed - NYI and possibly not necessary (unit dies mid scout?)
        };
        int priority;
        JobStatus status;
        int foodCount;
        BWAPI::TilePosition target;
        //std::vector<BWAPI::TilePosition> path; -- NYI: could be a bezier curve or simple point queue
        ScoutPriority() : status(Dormant) { }
    };
    ScoutManager(Arbitrator::Arbitrator<BWAPI::Unit*,double>* arbitrator);
    virtual void onOffer(std::set<BWAPI::Unit*> units);
    virtual void onRevoke(BWAPI::Unit* unit, double bid);
    virtual void update();
    void setInformationManager(InformationManager* infoManager);

    virtual std::string getName() const;
    virtual std::string getShortName() const;
    void onRemoveUnit(BWAPI::Unit* unit);
    bool isScoutingBase(BWTA::BaseLocation* base);

    // Non-Controller methods.
    int numScouts();
    void setDebugMode(bool debugMode);

    // List of scouting jobs that will be done in the future and a method to interface adding to the queue
    // The unit type is mapped to the list so that offered units can be accepted easier
    std::map<BWAPI::UnitType, std::list<ScoutPriority> > scoutJobs;
    void addJob(int priority, int foodCount=0, BWAPI::UnitType unit=BWAPI::UnitTypes::None, BWAPI::TilePosition target=BWAPI::TilePositions::None);

    std::map<BWAPI::Unit*, ScoutData> scouts;
    // maps a scout in spying mode to the time at which it starts spying
    std::map<BWAPI::Unit*, int> spyingScouts;
    // maps a unit to its pheramone trail
    //std::map<BWAPI::Unit*, PheramoneTrail*> pheramones;
    Arbitrator::Arbitrator<BWAPI::Unit*,double>* arbitrator;
    
    std::list<BWTA::BaseLocation*> baseLocationsToScout;
    std::set<BWTA::BaseLocation*> baseLocationsExplored;
    BWTA::BaseLocation *myStartLocation;
        
  private:
    void initialize();
    void addScout(BWAPI::Unit* unit);
    void updateScoutAssignments();
    void drawAssignments();
    InformationManager* informationManager;
    
    bool initialized;
    int scoutingStartFrame;
    bool debugMode;
};
